﻿using System;
using System.Collections.Generic;
using Newtonsoft.Json;

namespace JY.Common.Json
{
    /// <summary>
    /// JSON扩展
    /// </summary>
    public static class JsonExtension
    {
        #region # 序列化JSON —— static string ToJson(this object instance...
        /// <summary>
        /// 序列化JSON
        /// </summary>
        /// <param name="instance">实例</param>
        /// <param name="timeFormat">时间格式</param>
        /// <remarks>
        /// 类或者父级类标记了DataContractAttribute，则需要标记序列化。
        /// 1、类增加标记[JsonObject(MemberSerialization.OptOut)]
        /// 2、属性增加标记[JsonProperty]
        /// 排除序列化标记[JsonIgnore]
        /// </remarks>
        /// <returns>JSON</returns>
        public static string ToJson(this object instance, string timeFormat = null)
        {
            try
            {
                #region # 验证参数

                if (instance == null)
                {
                    return null;
                }

                #endregion
                JsonSerializerSettings settting = new JsonSerializerSettings
                {
                    ReferenceLoopHandling = ReferenceLoopHandling.Ignore
                };
                if (!string.IsNullOrWhiteSpace(timeFormat))
                {
                    settting.DateFormatString = timeFormat;
                }

                return JsonConvert.SerializeObject(instance, Formatting.None, settting);
            }
            catch (Exception exception)
            {
                throw new InvalidOperationException($"无法将给定实例序列化为JSON，请检查类型后重试！", exception);
            }
        }
        #endregion

        #region # JSON反序列化对象 —— static T AsJsonTo<T>(this string json)
        /// <summary>
        /// JSON反序列化对象
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="json">JSON</param>
        /// <returns>是否序列化成功</returns>
        public static T AsJsonTo<T>(this string json)
        {
            try
            {
                #region # 验证参数

                if (string.IsNullOrWhiteSpace(json))
                {
                    return default(T);
                }

                #endregion
                return JsonConvert.DeserializeObject<T>(json);
            }
            catch (Exception exception)
            {
                throw new InvalidOperationException($"无法将给定JSON反序列化为类型\"{typeof(T).Name}\"，请检查类型后重试！", exception);
            }
        }
        #endregion

        #region # 序列化JSON —— static string ToJson(this object instance...
        /// <summary>
        /// 序列化JSON
        /// </summary>
        /// <param name="instance">实例</param>
        /// <param name="timeFormat">时间格式</param>
        /// <remarks>
        /// 类或者父级类标记了DataContractAttribute，则需要标记序列化。
        /// 1、类增加标记[JsonObject(MemberSerialization.OptOut)]
        /// 2、属性增加标记[JsonProperty]
        /// 排除序列化标记[JsonIgnore]
        /// </remarks>
        /// <returns>JSON</returns>
        public static Tuple<bool, string, string> ToJsonResult(this object instance, string timeFormat = null)
        {
            try
            {
                #region # 验证参数

                if (instance == null)
                {
                    return new Tuple<bool, string, string>(false, "序列化失败！原因：实例为空！", null);
                }

                #endregion
                JsonSerializerSettings settting = new JsonSerializerSettings
                {
                    ReferenceLoopHandling = ReferenceLoopHandling.Ignore
                };
                if (!string.IsNullOrWhiteSpace(timeFormat))
                {
                    settting.DateFormatString = timeFormat;
                }

                return new Tuple<bool, string, string>(true, "序列化成功！", JsonConvert.SerializeObject(instance, Formatting.None, settting));
            }
            catch (Exception exception)
            {
                return new Tuple<bool, string, string>(false, $"无法将给定实例序列化为JSON，请检查类型后重试！\r异常消息：{exception.Message}", null);
            }
        }
        #endregion

        #region # JSON反序列化对象 —— static T AsJsonToResult<T>(this string json)
        /// <summary>
        /// JSON反序列化对象
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="json">JSON</param>
        /// <returns>是否序列化成功</returns>
        public static Tuple<bool, string, T> AsJsonToResult<T>(this string json)
        {
            try
            {
                #region # 验证参数

                if (string.IsNullOrWhiteSpace(json))
                {
                    return new Tuple<bool, string, T>(false, "数据为空！", default(T));
                }

                #endregion
                return new Tuple<bool, string, T>(true,"序列化成功", JsonConvert.DeserializeObject<T>(json));
            }
            catch (Exception exception)
            {
                return new Tuple<bool, string, T>(false, $"无法将给定JSON反序列化为类型\"{typeof(T).Name}\"，请检查类型后重试！\r异常消息：{exception.Message}", default(T));
            }
        }
        #endregion
    }
}
